package cn.edu.imau.zy.activiti.service.impl;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import cn.edu.imau.zy.common.core.entity.student.StStudent;
import cn.edu.imau.zy.common.core.entity.system.SysClasses;
import cn.edu.imau.zy.common.core.entity.system.SysDept;
import cn.edu.imau.zy.common.core.entity.system.SysUser;
import cn.edu.imau.zy.system.feign.RemoteClassesService;
import cn.edu.imau.zy.system.feign.RemoteDeptService;
import cn.edu.imau.zy.system.feign.RemoteStudentService;
import cn.edu.imau.zy.system.feign.RemoteUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import cn.edu.imau.zy.common.constant.ActivitiConstant;
import cn.edu.imau.zy.activiti.domain.BizNode;
import cn.edu.imau.zy.activiti.mapper.BizNodeMapper;
import cn.edu.imau.zy.activiti.service.IBizNodeService;
import cn.edu.imau.zy.activiti.vo.ProcessNodeVo;

import cn.hutool.core.util.StrUtil;

/**
 * 节点Service业务层处理
 * 
 *
 * @date 2020-01-07
 */
@Service
@Slf4j
public class BizNodeServiceImpl extends ServiceImpl<BizNodeMapper,BizNode> implements IBizNodeService
{
    @Autowired
    private BizNodeMapper     bizNodeMapper;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RemoteDeptService remoteDeptService;

    @Autowired
    private RemoteClassesService remoteClassesService;

    @Autowired
    private RemoteStudentService remoteStudentService;

    /**
     * 查询节点
     * 
     * @param id 节点ID
     * @return 节点
     */
    @Override
    public BizNode selectBizNodeById(Long id)
    {
        return bizNodeMapper.selectById(id);
//        return bizNodeMapper.selectByPrimaryKey(id);
    }

    /**
     * 查询节点列表
     * 
     * @param bizNode 节点
     * @return 节点
     */
    @Override
    public List<BizNode> selectBizNodeList(BizNode bizNode)
    {
//        return bizNodeMapper.select(bizNode);
        return bizNodeMapper.selectList(new QueryWrapper<>(bizNode));
    }

    /**
     * 新增节点
     * 
     * @param bizNode 节点
     * @return 结果
     */
    @Override
    public int insertBizNode(BizNode bizNode)
    {
        return bizNodeMapper.insert(bizNode);
//        return bizNodeMapper.insertSelective(bizNode);
    }

    /* (non-Javadoc)
     * @see IBizNodeService#setAuditors(java.lang.String)
     */
    @Override
    public ProcessNodeVo setAuditors(ProcessNodeVo node)
    {
        List<BizNode> bizNodes = selectBizNodeList(new BizNode().setNodeId(node.getNodeId()));
        //与集
        List<String> andRoleIds = Lists.newArrayList();
        List<String> andUserIds = Lists.newArrayList();
        List<String> andDeptIds = Lists.newArrayList();

        //或集
        List<String> orRoleIds = Lists.newArrayList();
        List<String> orUserIds = Lists.newArrayList();
        List<String> orDeptIds = Lists.newArrayList();
        for (BizNode bizNode : bizNodes)
        {
            if(bizNode.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND)){
                //属于与集
                // 设置关联角色
                if (bizNode.getType().equals(ActivitiConstant.NODE_ROLE))
                {
                    andRoleIds.add(bizNode.getAuditor());
                }
                // 设置关联部门
                else if (bizNode.getType().equals(ActivitiConstant.NODE_DEPARTMENT))
                {
                    andDeptIds.add(bizNode.getAuditor());
                }
                // 设置关联用户
                else if (bizNode.getType().equals(ActivitiConstant.NODE_USER))
                {
                    andUserIds.add(bizNode.getAuditor());
                }
                else if (bizNode.getType().equals(ActivitiConstant.NODE_DEP_HEADER))
                {
                    // 是否设置操作人负责人
                    node.setAndDeptHeader(true);
                }
                else if (bizNode.getType().equals(ActivitiConstant.NODE_CLASS_DIRECTOR))
                {
                    // 是否所属班级班主任
                    node.setAndClassDirector(true);
                }else if(bizNode.getType().equals(ActivitiConstant.NODE_EQUAL_DEPT)){
                    // 是否相同部门
                    node.setAndEqualDept(true);
                } else if (bizNode.getType().equals(ActivitiConstant.NODE_SECRETARY)) {
                    // 是否系书记
                    node.setSecretary(true);
                } else if (bizNode.getType().equals(ActivitiConstant.NODE_OFFICE)) {
                    // 是否系学办主任
                    node.setOffice(true);
                } else if (bizNode.getType().equals(ActivitiConstant.NODE_APPLYER)) {
                    // 是否系学办主任
                    node.setApplyer(true);
                }
            }else if(bizNode.getLogic().equals(ActivitiConstant.NODE_LOGIC_OR)){
                //属于或集
                // 设置关联角色
                if (bizNode.getType().equals(ActivitiConstant.NODE_ROLE))
                {
                    orRoleIds.add(bizNode.getAuditor());
                }
                // 设置关联部门
                else if (bizNode.getType().equals(ActivitiConstant.NODE_DEPARTMENT))
                {
                    orDeptIds.add(bizNode.getAuditor());
                }
                // 设置关联用户
                else if (bizNode.getType().equals(ActivitiConstant.NODE_USER))
                {
                    orUserIds.add(bizNode.getAuditor());
                }
                else if (bizNode.getType().equals(ActivitiConstant.NODE_DEP_HEADER))
                {
                    // 是否设置操作人负责人
                    node.setOrDeptHeader(true);
                }
                else if (bizNode.getType().equals(ActivitiConstant.NODE_CLASS_DIRECTOR))
                {
                    // 是否所属班级班主任
                    node.setOrClassDirector(true);
                }else if(bizNode.getType().equals(ActivitiConstant.NODE_EQUAL_DEPT)){
                    // 是否相同部门
                    node.setOrEqualDept(true);
                }
            }

        }
        // 设置关联角色
        node.setOrRoleIds(orRoleIds);
        // 设置关联部门
        node.setOrDeptIds(orDeptIds);
        // 设置关联用户
        node.setOrUserIds(orUserIds);

        // 设置关联角色
        node.setAndRoleIds(andRoleIds);
        // 设置关联部门
        node.setAndDeptIds(andDeptIds);
        // 设置关联用户
        node.setAndUserIds(andUserIds);
        return node;
    }

    /* (non-Javadoc)
     * @see IBizNodeService#updateBizNode(ProcessNodeVo)
     */
    @Override
    public int updateBizNode(ProcessNodeVo node)
    {
        // 删除所有节点信息
//        bizNodeMapper.delete(new BizNode().setNodeId(node.getNodeId()));
        bizNodeMapper.delete(new QueryWrapper<>(new BizNode().setNodeId(node.getNodeId())));
        List<BizNode> bizNodes = Lists.newArrayList();
        //与集处理
        List<String> andRoleIds = node.getAndRoleIds();
        if (null != andRoleIds && andRoleIds.size() > 0)
        {
            for (String roleId : andRoleIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_ROLE)
                        .setAuditor(roleId).setLogic(ActivitiConstant.NODE_LOGIC_AND));
            }
        }
        List<String> andDeptIds = node.getAndDeptIds();
        if (null != andDeptIds && andDeptIds.size() > 0)
        {
            for (String deptId : andDeptIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_DEPARTMENT)
                        .setAuditor(deptId).setLogic(ActivitiConstant.NODE_LOGIC_AND));
            }
        }
        List<String> andUserIds = node.getAndUserIds();
        if (null != andUserIds && andUserIds.size() > 0)
        {
            for (String userId : andUserIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_USER)
                        .setAuditor(userId).setLogic(ActivitiConstant.NODE_LOGIC_AND));
            }
        }
        if (null != node.getAndDeptHeader() && node.getAndDeptHeader())
        {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_DEP_HEADER).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }
        if (null != node.getAndClassDirector() && node.getAndClassDirector())
        {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_CLASS_DIRECTOR).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }
        if(null != node.getAndEqualDept() && node.getAndEqualDept()){
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_EQUAL_DEPT).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }
        if (null != node.getSecretary() && node.getSecretary()) {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_SECRETARY).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }
        if (null != node.getOffice() && node.getOffice()) {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_OFFICE).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }
        if (null != node.getApplyer() && node.getApplyer()) {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_APPLYER).setLogic(ActivitiConstant.NODE_LOGIC_AND));
        }

        //或集处理
        List<String> orRoleIds = node.getOrRoleIds();
        if (null != orRoleIds && orRoleIds.size() > 0)
        {
            for (String roleId : orRoleIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_ROLE)
                        .setAuditor(roleId).setLogic(ActivitiConstant.NODE_LOGIC_OR));
            }
        }
        List<String> orDeptIds = node.getOrDeptIds();
        if (null != orDeptIds && orDeptIds.size() > 0)
        {
            for (String deptId : orDeptIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_DEPARTMENT)
                        .setAuditor(deptId).setLogic(ActivitiConstant.NODE_LOGIC_OR));
            }
        }
        List<String> orUserIds = node.getOrUserIds();
        if (null != orUserIds && orUserIds.size() > 0)
        {
            for (String userId : orUserIds)
            {
                bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_USER)
                        .setAuditor(userId).setLogic(ActivitiConstant.NODE_LOGIC_OR));
            }
        }
        if (null != node.getOrDeptHeader() && node.getOrDeptHeader())
        {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_DEP_HEADER).setLogic(ActivitiConstant.NODE_LOGIC_OR));
        }
        if (null != node.getOrClassDirector() && node.getOrClassDirector())
        {
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_CLASS_DIRECTOR).setLogic(ActivitiConstant.NODE_LOGIC_OR));
        }
        if(null != node.getOrEqualDept() && node.getOrEqualDept()){
            bizNodes.add(new BizNode().setNodeId(node.getNodeId()).setType(ActivitiConstant.NODE_EQUAL_DEPT).setLogic(ActivitiConstant.NODE_LOGIC_OR));
        }
        int insert = 0 ;
        if (bizNodes.isEmpty()){
            for (BizNode bizNode : bizNodes) {

                insert = bizNodeMapper.insert(bizNode);

            }
        }else{
            return 0;
        }
        return  0;
       
        
        
//        return bizNodes.isEmpty() ? 0 : bizNodeMapper.insertList(bizNodes);
    }

    /* (non-Javadoc)
     * @see IBizNodeService#getAuditors(java.lang.String)
     */
    @Override
    public Set<String> getAuditors(String nodeId, String userId)
    {
        // TODO 优化查询次数可以将同类型审核人一次性查询得到
        List<BizNode> bizNodes = selectBizNodeList(new BizNode().setNodeId(nodeId));
        Set<String> auditors = Sets.newHashSet();
        Set<String> orRoleIds = Sets.newHashSet();
        Set<String> orDeptIds = Sets.newHashSet();

        Set<String> andRoleIds = Sets.newHashSet();
        Set<String> andDeptIds = Sets.newHashSet();
        Set<String> andEqualDeptIds = Sets.newHashSet();

        Set<String> andSet1 = Sets.newHashSet();
        Set<String> andSet2 = Sets.newHashSet();
        Set<String> andSet3 = Sets.newHashSet();
        Set<String> andSet4 = Sets.newHashSet();
        Set<String> andSet5 = Sets.newHashSet();
        Set<String> andSet6 = Sets.newHashSet();
        Set<String> andSet7 = Sets.newHashSet();
        Set<String> andSet8 = Sets.newHashSet();
        Set<String> andSet9 = Sets.newHashSet();

        Set<String> andResult = Sets.newHashSet();
        if (null != bizNodes && bizNodes.size() > 0)
        {
            for (BizNode node : bizNodes)
            {
                if (node.getType().equals(ActivitiConstant.NODE_USER))
                {
                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andSet1 : auditors;
                    // 用户类型放入集合1 备选
                    tmp.add(node.getAuditor());
                }
                else if (node.getType().equals(ActivitiConstant.NODE_ROLE))
                {
                    // 查询所有拥有有当前角色编号的用户
                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andRoleIds : orRoleIds;
                    tmp.add(node.getAuditor());
                }
                else if (node.getType().equals(ActivitiConstant.NODE_DEPARTMENT))
                {
                    // 查询对应部门的人员
                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andDeptIds : orDeptIds;
                    tmp.add(node.getAuditor());
                }
                else if (node.getType().equals(ActivitiConstant.NODE_DEP_HEADER))
                {
                    // 当前用户部门的负责人
                    SysUser user = remoteUserService.selectSysUserByUserId(userId);
                    SysDept dept = remoteDeptService.selectSysDeptByDeptId(user.getDeptId());

                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andSet2 : auditors;
                    tmp.add(dept.getLeaderId().toString());
                }
                else if (node.getType().equals(ActivitiConstant.NODE_CLASS_DIRECTOR))
                {
                    // 申请人班级的班主任
                    StStudent student = remoteStudentService.getStudentById(userId);

                    // 获取班级信息
                    SysClasses classes = remoteClassesService.getClassesById(student.getClassesId());
                    SysUser director = new SysUser();
                    director.setUserId(classes.getDirectorId().toString());
                    //老师类型
                    director.setUserType("2");
                    director = remoteUserService.getByParams(director);

                    // 根据班级信息中的班主任信息id 和教师用户类型2 查询唯一的班主任帐号信息
                    //把班主任帐号的ID放入集合


                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andSet5 : auditors;
                    tmp.add(director.getUserId());
                }
                else if(node.getType().equals(ActivitiConstant.NODE_EQUAL_DEPT)){
                    //与申请人同主体
                    Set<String> tmp = node.getLogic().equals(ActivitiConstant.NODE_LOGIC_AND) ? andEqualDeptIds : orDeptIds;
                    tmp.add(node.getAuditor());
                } else if (node.getType().equals(ActivitiConstant.NODE_SECRETARY)) {
                    //系书记
                    SysUser user = remoteUserService.selectSysUserByUserId(userId);
                    SysDept dept = remoteDeptService.selectSysDeptByDeptId(user.getDeptId());

                    andSet7.add(dept.getSecretaryId());
                } else if (node.getType().equals(ActivitiConstant.NODE_OFFICE)) {
                    //系学办主任
                    SysUser user = remoteUserService.selectSysUserByUserId(userId);
                    SysDept dept = remoteDeptService.selectSysDeptByDeptId(user.getDeptId());
                    andSet8.add(dept.getOfficeId());
                } else if (node.getType().equals(ActivitiConstant.NODE_APPLYER)) {
                    // 申请人
                    andSet9.add(userId);
                }


            }
        }
        //与集拿出备选
        if (andRoleIds.size() > 0){
            andSet3.addAll(remoteUserService.selectUserIdsHasRoles(StrUtil.join(",", andRoleIds.toArray())));
        }
        if (andDeptIds.size() > 0){
            andSet4.addAll(remoteUserService.selectUserIdsInDepts(StrUtil.join(",", andDeptIds.toArray())));
        }
        if(andSet6.size() > 0){
            andSet6.addAll(remoteUserService.selectUserIdsInDepts(StrUtil.join(",", andEqualDeptIds.toArray())));
        }

        List<Set<String>> andSets = Lists.newArrayList();
        andSets.add(andSet1);
        andSets.add(andSet2);
        andSets.add(andSet3);
        andSets.add(andSet4);
        andSets.add(andSet5);
        andSets.add(andSet6);
        andSets.add(andSet7);
        andSets.add(andSet8);
        andSets.add(andSet9);
        //与集求交集 不为空的与集才能参与求交集
        for (Set<String> andSet : andSets) {
            if(andSet.size() > 0 && andResult.size() > 0){
                andResult.retainAll(andSet);
                if(andResult.size() == 0){
                    //在某几个子集没有交集的时候停止求交集
                    break;
                }
            }else if(andSet.size() > 0){
                andResult.addAll(andSet);
            }
        }

        //或集直接存入结果集
        if (orRoleIds.size() > 0)
        {
            auditors.addAll(remoteUserService.selectUserIdsHasRoles(StrUtil.join(",", orRoleIds.toArray())));
        }
        if (orDeptIds.size() > 0)
        {
            auditors.addAll(remoteUserService.selectUserIdsInDepts(StrUtil.join(",", orDeptIds.toArray())));
        }

        //与集存入结果集
        auditors.addAll(andResult);
        log.info("下一流程处理人员:{}", auditors);
        return auditors;
    }
}
